// View Animation Extentions

(function (R) {
  var animations = [
    'slideInLeft', 'slideInRight', 'slideOutLeft', 'slideOutRight',
    'slideInUp', 'slideInDown', 'slideOutUp', 'slideOutDown',
  ];

  var EVENTS = 'removeAnimate webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend';
  //animate
  var animationExtentions = {
    animate: function(name, options, cb) {
      options = options || {reverse: true};


      // 只传两个参数，如果第二个参数是函数，则认为是callback
      if ( $.isFunction(options) ) {
        cb = options;
        options = null;
      }
      // defaults
      options = _.defaults(options || {}, {
        reverse: true,
        duration: 1000, // ms
        infinite: false
      });

      // timeout promise
      var timeoutPromise = new Promise(function(resolve, reject){
        var timeout = setTimeout(resolve, options.duration + 100);
        this.timeout = timeout;
      }.bind(this));

      //animated promise
      var animationend = new Promise(function(resolve, reject){
        this.$el.addClass('animated ' + name);
        this.$el.one(EVENTS, function() {
          clearTimeout(this.timeout);
          if (options.reverse) this.$el.removeClass('animated ' + name);
          resolve();
        }.bind(this));
      }.bind(this));

      // 动画完成或计时器超时，任一条件达成，此机制用于处理android的动画完成函数回调不及时的问题
      return Promise.race([animationend, timeoutPromise])
      .then(function(){
        cb && cb();
      });


    }
  };

  //transform animation name array to <name: fn> mapping json object
  var animationExtentions =
    animations.reduce(function(_this, animation) {
      var fn_name = 'animate' + animation.charAt(0).toUpperCase() + animation.substring(1);
      _this[fn_name] = function(options) {
        return this.animate(animation, options);
      }
      return _this;
    }, animationExtentions);

  _.extend(R.View.prototype, animationExtentions);

}(rweb, window, document))
